﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SQLToolbox.Types
{
	/// <summary>
	/// Represents the locator of server instances
	/// </summary>
	public interface IServerLocator
	{
		/// <summary>
		/// Gets the servers list.
		/// </summary>
		/// <value>The servers list.</value>
		IEnumerable<string> ServersList { get; }
	}

	/// <summary>
	/// Represent the provider of access to the database schema 
	/// </summary>
	public interface IServerSchemaProvider
	{
		/// <summary>
		/// Connects o the specified server .
		/// </summary>
		/// <param name="dcp">The Database Connection Properties.</param>
		void SetConnection(DBConnectionProperties dcp);


		/// <summary>
		/// Gets the version of the server
		/// </summary>
		string ServerVersion { get; }
		/// <summary>
		/// Gets the databases on the server.
		/// </summary>
		/// <value>The databases.</value>
		List<string> Databases { get; }
		/// <summary>
		/// Gets the schema of the database by name
		/// </summary>
		/// <param name="databaseName"></param>
		/// <returns></returns>
		Schema GetSchema(string databaseName);


		/// <summary>
		/// Gets the schema.
		/// </summary>
		/// <param name="databaseName">Name of the database.</param>
		/// <param name="requiredProperties">The required properties.</param>
		/// <returns></returns>
		Schema GetSchema(string databaseName, IDictionary<SchemaObjectType, IEnumerable<string>> requiredProperties);

		/// <summary>
		/// Gets the object from the databases schema.
		/// </summary>
		/// <param name="databaseName">Name of the database.</param>
		/// <param name="type">The type of the object to retrieve.</param>
		/// <param name="objectName">Name of the object.</param>
		/// <returns></returns>
		SchemaObject GetObject(string databaseName, SQLToolbox.Types.SchemaObjectType type, string objectName);

  		/// <summary>
		/// Fired when starting to process new database object
		/// </summary>
		event EventHandler<DatabaseObjectProcessingEventArgs> DatabaseObjectProcessing;
	}


	public class DatabaseObjectProcessingEventArgs : EventArgs
	{
		public SchemaObjectType ObjectType { get; set; }
		public string ObjectName { get; set; }
	}

	/// <summary>
	/// Represent the factory for the match script
    /// Works in transactional manner - init target (and source if needed) database(s)
    /// Do the actions and then - get the captured script
	/// </summary>
	public interface ISchemaObjectsMatcher
	{
        /// <summary>
        /// Inits the source database.
        /// </summary>
        /// <param name="sourceConnection">The source connection.</param>
        void InitSourceDatabase(DBConnectionProperties sourceConnection);

        /// <summary>
        /// Inits the target database.
        /// </summary>
        /// <param name="targetConnection">The target connection.</param>
        void InitTargetDatabase(DBConnectionProperties targetConnection);
        
        
        /// <summary>
		/// Creates alter script from source to target.
		/// </summary>
		/// <param name="sourceConnection">The source connection.</param>
		/// <param name="targetConnection">The target connection.</param>
		/// <param name="obj">The obj.</param>
		/// <returns></returns>
		void CreateAlterScript(SQLToolbox.Types.SchemaObjectBase obj);
		/// <summary>
		/// Creates drop script at a target.
		/// </summary>
		/// <param name="targetConnection">The target connection.</param>
		/// <param name="obj">The obj.</param>
		/// <returns></returns>
        void CreateDropScript(SQLToolbox.Types.SchemaObjectBase obj);

        /// <summary>
        /// Finishes the batch of commands and returns the captured script from the target.
        /// </summary>
        /// <returns></returns>
        Script FinishBatch();
       
    }

	/// <summary>
	/// Executes script on a database.
	/// </summary>
	public interface IDatabaseScriptExecuter
	{
		/// <summary>
		/// Executes the script.
		/// </summary>
		/// <param name="dcp">The Database Connection Properties.</param>
		/// <param name="script">The script.</param>
		void ExecuteScriptNonQuery(DBConnectionProperties dcp, Script script);
		/// <summary>
		/// Executes the script.
		/// </summary>
		/// <param name="dcp">The Database Connection Properties.</param>
		/// <param name="script">The script.</param>
		IEnumerable<System.Data.DataTable> ExecuteScript(DBConnectionProperties dcp, Script script);
	}

	[global::System.Serializable]
	public class SQLTooboxDALException : Exception
	{
		//
		// For guidelines regarding the creation of new exception types, see
		//    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp
		// and
		//    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp
		//

		/// <summary>
		/// Initializes a new instance of the <see cref="SQLTooboxDALException"/> class.
		/// </summary>
		public SQLTooboxDALException() { }
		/// <summary>
		/// Initializes a new instance of the <see cref="SQLTooboxDALException"/> class.
		/// </summary>
		/// <param name="message">The message.</param>
		public SQLTooboxDALException(string message) : base(message) { }
		/// <summary>
		/// Initializes a new instance of the <see cref="SQLTooboxDALException"/> class.
		/// </summary>
		/// <param name="message">The message.</param>
		/// <param name="inner">The inner.</param>
		public SQLTooboxDALException(string message, Exception inner) : base(message, inner) { }
		/// <summary>
		/// Initializes a new instance of the <see cref="SQLTooboxDALException"/> class.
		/// </summary>
		/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
		/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
		/// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> parameter is null. </exception>
		/// <exception cref="T:System.Runtime.Serialization.SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0). </exception>
		protected SQLTooboxDALException(
		  System.Runtime.Serialization.SerializationInfo info,
		  System.Runtime.Serialization.StreamingContext context)
			: base(info, context) { }
	}
}
